package com.googlecode.cswish.struts;

import javax.annotation.Resource;

import com.googlecode.cswish.Config;
import com.googlecode.cswish.struts.spring.BeanIntrospector;

/**
 * Routing table
 * 
 * @author jerry.feng Date: 2008-9-25
 */
public class Routing {

	@Resource
	protected BeanIntrospector beanIntrospector;
	
	@Resource
	protected Config config;
	
	public int findMethodSeparator(String path) {
		int index;
		boolean enableSlashSep = false; // TODO
		for (index = path.length() - 1; index >= 0; index--) {
			char c = path.charAt(index);
			if (c != '_' && !Character.isLetterOrDigit(c)) {
				if (enableSlashSep) {
					break;
				} else if (c != '/' && c != '\\') {
					break;
				}
			}
		}
		return index;
	}
	
	public Invoker action2Invoker(String actionClassName) {
		int index = findMethodSeparator(actionClassName);

		char separator = '.';
		String methodName = null;
		if (index >= 0) {
			separator = actionClassName.charAt(index);
			// first character should be low case
			int endPos = actionClassName.length() - config.getActionPackageSuffixs()[0].length();
			if (endPos > index) {
				methodName = Character.toLowerCase(actionClassName.charAt(index + 1)) + 
					actionClassName.substring(index + 2, endPos);
			}
		}
		if (methodName == null) {
			separator = '.';
			methodName = "execute";
		}
		return new Invoker(actionClassName, separator, methodName);
	}
	
	public Invoker path2Invoker(String path) {
		int index = findMethodSeparator(path);
		
		String className;
		String methodName;
		char separator;
		if (index > 0) {
			methodName = path.substring(index + 1);
			separator = path.charAt(index);
			// class name can't contain '/'
			if (separator == '/') {
				separator = '\\';
			}
		} else {
			methodName = "execute";
			index = path.length();
			separator = '.';
		}
		
		className = config.getActionPackage()
			+ path.substring(0, index).replace('/', '.');
		String actionClassName = className + separator 
			+ Character.toUpperCase(methodName.charAt(0)) + methodName.substring(1) 
			+ config.getActionPackageSuffixs()[0];
		return new Invoker(actionClassName, separator, methodName);
	}
	
	public String invoker2Path(Invoker invoker) {
		String simpleName = beanIntrospector.getSimpleName(invoker.actionName);
		String path = simpleName.replace('.', '/');
		if (invoker.methodName == null) {
			return path;
		} else {
			return path + invoker.separator + invoker.methodName;
		}
	}
}